package com.android.tnovoselec.travelassistant.activity;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ViewFlipper;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.android.tnovoselec.travelassistant.Config;
import com.android.tnovoselec.travelassistant.Constant;
import com.android.tnovoselec.travelassistant.R;
import com.android.tnovoselec.travelassistant.adapter.BenzinskeAdapter;
import com.android.tnovoselec.travelassistant.async.BenzinskeRefresher;
import com.android.tnovoselec.travelassistant.async.BenzinskeSearcher;
import com.android.tnovoselec.travelassistant.async.TravelAssistantGeocoder;
import com.android.tnovoselec.travelassistant.db.TravelAssistantDatabaseHelper;
import com.android.tnovoselec.travelassistant.dto.BenzinskaDto;
import com.android.tnovoselec.travelassistant.dto.BenzinskeResultHolder;
import com.android.tnovoselec.travelassistant.overlay.BenzinskeAROverlayNavigation;
import com.android.tnovoselec.travelassistant.overlay.BenzinskeOverlay;
import com.android.tnovoselec.travelassistant.overlay.BenzinskeOverlay.BenzinskaSelectedListener;
import com.android.tnovoselec.travelassistant.view.CustomMapView;
import com.android.tnovoselec.travelassistant.view.CustomMapView.OnMapMovedListener;
import com.android.tnovoselec.travelassistant.view.CustomMapView.OnZoomLevelChangeLister;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MyLocationOverlay;
import com.j256.ormlite.dao.Dao;
import com.nth.android.ar.ARAugmentedView;
import com.nth.android.ar.ARCameraView;
import com.nth.android.common.async.Async;
import com.nth.android.common.async.listener.Outcome;
import com.nth.android.common.async.notif.NotifierFactory;
import com.nth.android.lbs.location.MyLocationService;
import com.nth.android.orm.apptools.OrmLiteBaseFragmentMapActivity;
import com.nth.android.ui.quickaction.ActionItem;
import com.nth.android.ui.quickaction.QuickAction;
import com.nth.android.ui.quickaction.QuickAction.OnActionItemClickListener;

public class BenzinskeMapActivity extends OrmLiteBaseFragmentMapActivity<TravelAssistantDatabaseHelper> implements OnMapMovedListener,
		BenzinskaSelectedListener, AnimationListener, OnItemClickListener, OnClickListener, LocationListener, OnZoomLevelChangeLister, OnKeyListener,
		OnActionItemClickListener {

	public enum VIEWS {
		MAP, LIST, AR
	}

	public static String TAG = BankomatiMapActivity.class.getSimpleName();

	CustomMapView mapView;
	protected ProgressDialog dialog = null;
	private Handler handler = new Handler();
	private Dao<BenzinskaDto, String> benzinskaDao = null;
	private BenzinskeOverlay benzinskeOverlay;
	protected MyLocationOverlay locationOverlay;
	protected MyLocationService locationService = null;
	protected ARCameraView arCameraView;
	protected ARAugmentedView arAugmentedView;
	private ListView list;
	private Location lastLocation;
	private ViewFlipper viewFlipper;
	private BenzinskeAdapter adapter;

	private View searchContainer;
	private EditText query;
	private ImageView cancel;

	private ImageButton mapMode;
	private ImageButton listMode;
	private ImageButton arMode;

	private Animation animShow;
	private Animation animHide;

	private QuickAction quickAction;
	private View gasStationChooser;

	private static final int INA_ID = 1;
	private static final int CROBENZ_ID = 2;
	private static final int OMV_ID = 3;
	private static final int PETROL_ID = 4;
	private static final int ALL_ID = 5;

	private String activeType = "";
	private VIEWS activeView = VIEWS.MAP;

	private boolean isSearchActivated = false;
	private boolean lock = false;

	private static final Criteria CRITERIA = new Criteria();
	static {
		CRITERIA.setAccuracy(Criteria.ACCURACY_COARSE);
		CRITERIA.setAltitudeRequired(false);
		CRITERIA.setBearingRequired(false);
		CRITERIA.setCostAllowed(true);
		CRITERIA.setSpeedRequired(false);
		CRITERIA.setPowerRequirement(Criteria.NO_REQUIREMENT);
	}

	@SuppressWarnings("deprecation")
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.benzinske_map);

		try {
			benzinskaDao = this.getHelper().getBenzinskaDao();
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		viewFlipper = (ViewFlipper) findViewById(R.id.benzinske_viewflipper);
		list = (ListView) findViewById(R.id.benzinske_list);

		searchContainer = findViewById(R.id.search_popup_container);
		searchContainer.bringToFront();

		query = (EditText) findViewById(R.id.search_popup_edittext);
		query.setOnKeyListener(this);

		cancel = (ImageView) findViewById(R.id.search_popup_cancel);
		cancel.setOnClickListener(this);

		mapMode = (ImageButton) findViewById(R.id.benzinske_map_mode);
		listMode = (ImageButton) findViewById(R.id.benzinske_list_mode);
		arMode = (ImageButton) findViewById(R.id.benzinske_ar_mode);

		mapMode.setOnClickListener(this);
		listMode.setOnClickListener(this);
		arMode.setOnClickListener(this);

		list.setOnItemClickListener(this);

		mapView = (CustomMapView) findViewById(R.id.benzinske_map);
		mapView.setSatellite(false);
		mapView.setStreetView(false);
		// mapView.setBuiltInZoomControls(true);
		
		locationOverlay = new MyLocationOverlay(this, mapView);
		mapView.getOverlays().add(locationOverlay);
		//mapView.getController().setZoom(13);
		mapView.animateTo(new GeoPoint((int)(Config.zgLat*1e6), (int)(Config.zgLng*1e6)));
		mapView.invalidate();

		locationService = new MyLocationService(this, this, CRITERIA);

		arCameraView = (ARCameraView) findViewById(R.id.benzinske_ar_camera_view);
		arAugmentedView = (ARAugmentedView) findViewById(R.id.benzinske_ar_augmented_view);
		arAugmentedView.setShowRadar(true);
		arAugmentedView.setRadarPoiResourceId(R.drawable.poi_radar);
		arAugmentedView.setRadarBackgroundResourceId(R.drawable.background_ar_radar);

		adapter = new BenzinskeAdapter(this);
		list.setAdapter(adapter);

		animShow = AnimationUtils.loadAnimation(this, R.anim.popup_show);
		animHide = AnimationUtils.loadAnimation(this, R.anim.popup_hide);
		animHide.setAnimationListener(this);

		ActionItem inaAction = new ActionItem(INA_ID, getString(R.string.ina_title), getResources().getDrawable(R.drawable.ina_icon));
		ActionItem crobenzAction = new ActionItem(CROBENZ_ID, getString(R.string.crobenz_title), getResources().getDrawable(R.drawable.crobenz_icon));
		ActionItem omvAction = new ActionItem(OMV_ID, getString(R.string.omv_title), getResources().getDrawable(R.drawable.omv_icon));
		ActionItem petrolAction = new ActionItem(PETROL_ID, getString(R.string.petrol_title), getResources().getDrawable(R.drawable.petrol_icon));
		ActionItem allAction = new ActionItem(ALL_ID, getString(R.string.all_gas_title), getResources().getDrawable(R.drawable.all));

		quickAction = new QuickAction(this, QuickAction.VERTICAL);
		quickAction.addActionItem(inaAction);
		quickAction.addActionItem(crobenzAction);
		quickAction.addActionItem(omvAction);
		quickAction.addActionItem(petrolAction);

		quickAction.addActionItem(allAction);
		quickAction.setOnActionItemClickListener(this);

		search(MyLocationService.getLastKnownGeoPoint(this), VIEWS.MAP);
	}

	@Override
	protected void onResume() {
		super.onResume();
		arAugmentedView.start();
		arAugmentedView.setLocation(MyLocationService.getLastKnownLocation(this));
		try {
			if (locationOverlay != null) {
				locationOverlay.enableMyLocation();
				// locationOverlay.enableCompass();
			}
			if (locationService != null) {
				locationService.trackMyLocation();
			}
		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		mapView.registerOnMapMovedListener(this);
		mapView.registerOnZoomLevelChangedListener(this);
	}

	@Override
	protected void onPause() {
		super.onPause();
		arAugmentedView.stop();
		try {
			if (locationOverlay != null) {
				locationOverlay.disableMyLocation();
				locationOverlay.disableCompass();
			}
			if (locationService != null) {
				locationService.stopTrackingMyLocation();
			}

		} catch (Exception e) {
			Log.e(TAG, e.getMessage());
		}
		mapView.unregisterOnMapMovedListener();
		mapView.unregisterOnZoomChangedListener();
	}

	protected synchronized void search(final GeoPoint geoPoint, final VIEWS view) {
		dialog = ProgressDialog.show(this, "", super.getResources().getText(R.string.please_wait), true);

		Async.doAsync(null, new BenzinskeSearcher(this, benzinskaDao, geoPoint, activeType), new Outcome<Void, Boolean>() {

			@SuppressWarnings("synthetic-access")
			@Override
			protected void succeeded(Void key, Boolean result) {
				dialog.dismiss();

				if (result.booleanValue()) {
					if (view == VIEWS.MAP) {
						Drawable mapPin = getResources().getDrawable(R.drawable.map_pin);
						benzinskeOverlay = new BenzinskeOverlay(BenzinskeMapActivity.this, mapPin, BenzinskeResultHolder.getAllBenzinske(), mapView);
						benzinskeOverlay.setListener(BenzinskeMapActivity.this);
						// benzinskeOverlay.adjustMapViewToPOIs(mapView,
						// MyLocationService.getLastKnownGeoPoint(BenzinskeMapActivity.this));
						benzinskeOverlay.adjustMapViewToPOIs(mapView, null);
						mapView.getOverlays().clear();
						mapView.getOverlays().add(benzinskeOverlay);
					} else if (view == VIEWS.AR) {

						BenzinskeAROverlayNavigation overlay = new BenzinskeAROverlayNavigation(arAugmentedView);
						overlay.setPoiARList(BenzinskeResultHolder.getAllBenzinske());
						arAugmentedView.removeAllOverlays();
						arAugmentedView.addOverlay(overlay);
						arAugmentedView.setLocation(MyLocationService.getLastKnownLocation(BenzinskeMapActivity.this));
					}
				} else {
					// ImageToast.show(HomeActivity.this, R.drawable.icon,
					// R.string.no_result);
				}

			}

			@Override
			protected void failed(Void key, Throwable error) {
				dialog.dismiss();

				Log.e(TAG, "Exception: ", error);
			}
		}, NotifierFactory.newThreadSpecificNotifier(handler));
	}

	@Override
	public void onZoomLevelChanged(int oldZoomLevel, int newZoomLevel) {
		Log.i(TAG, "Zoom changed from " + oldZoomLevel + " to " + newZoomLevel);

	}

	@Override
	public void onMapMoved(GeoPoint tl, GeoPoint br) {
		Async.doAsync(null, new BenzinskeRefresher(this, benzinskaDao, tl, br , activeType), new Outcome<Void, Boolean>() {

			@SuppressWarnings("synthetic-access")
			@Override
			protected void succeeded(Void key, Boolean result) {
				if (result.booleanValue()) {
					handler.removeCallbacks(updateMap);
					handler.postDelayed(updateMap, 1000L);
				} else {
					// NIX
				}

			}

			@Override
			protected void failed(Void key, Throwable t) {
				// NIX

			}
		}, NotifierFactory.newThreadSpecificNotifier(handler));

	}

	private Runnable updateMap = new Runnable() {

		@SuppressWarnings("synthetic-access")
		@Override
		public void run() {
			Drawable mapPin = getResources().getDrawable(R.drawable.map_pin);
			benzinskeOverlay = new BenzinskeOverlay(BenzinskeMapActivity.this, mapPin, BenzinskeResultHolder.getAllBenzinske(), mapView);
			benzinskeOverlay.setListener(BenzinskeMapActivity.this);
			// bankomatiOverlay.adjustMapViewToPOIs(mapView, null);
			mapView.getOverlays().clear();
			mapView.getOverlays().add(benzinskeOverlay);
			mapView.getOverlays().add(locationOverlay);
			mapView.invalidate();
		}
	};

	@SuppressWarnings("null")
	@Override
	public void onLocationChanged(Location location) {
		int geoLat = (int) (location.getLatitude() * 1E6);
		int geoLng = (int) (location.getLongitude() * 1E6);

		// mapView.getController().setZoom(10);
		mapView.animateTo(new GeoPoint(geoLat, geoLng));
		mapView.invalidate();

		if (location != null) {
			if (lastLocation == null) {
				lastLocation = location;
			}
			float[] distance = new float[3];
			Location.distanceBetween(lastLocation.getLatitude(), lastLocation.getLongitude(), location.getLatitude(), location.getLongitude(), distance);
			if (viewFlipper.getDisplayedChild() == 2) {
				search(MyLocationService.getLastKnownGeoPoint(this), VIEWS.AR);
			}
		}

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// NIX

	}

	@Override
	public void onProviderEnabled(String provider) {
		// NIX

	}

	@Override
	public void onProviderDisabled(String provider) {
		// NIX

	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		if (item.getItemId() == R.id.menu_benzinske_search) {
			if (viewFlipper.getDisplayedChild() != 0) {
				viewFlipper.setDisplayedChild(0);

			}
			if (isSearchActivated) {
				hideSearchPopup();
			} else {
				showSearchPopup();
			}

		} else if (item.getItemId() == R.id.menu_benzinske_more) {
			quickAction.show(gasStationChooser);
		} else if (item.getItemId() == android.R.id.home) {
			finish();
		}
		benzinskeOverlay.hidePopup();
		return true;

	}

	private void updateList() {
		adapter.setData(BenzinskeResultHolder.getAllBenzinske());
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getSupportMenuInflater().inflate(R.menu.benzinske_menu, menu);
		for (int i = 0; i < menu.size(); i++) {
			MenuItem item = menu.getItem(i);
			if (item.getItemId() == R.id.menu_benzinske_more) {
				gasStationChooser = item.getActionView();
				if (gasStationChooser != null) {
					gasStationChooser.setOnClickListener(this);
				}
			}
		}
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		viewFlipper.setDisplayedChild(0);
		BenzinskaDto item = (BenzinskaDto) adapter.getItem(position);
		// mapView.disableOnMoveListener();
		// mapView.animateTo(item.getGeoPoint());
		if (benzinskeOverlay != null) {
			benzinskeOverlay.handleListClick(item);
		}
	}

	@Override
	public void onClick(View v) {

		if (v == mapMode) {
			hideSearchPopup();
			viewFlipper.setDisplayedChild(0);
			activeView = VIEWS.MAP;
//			search(MyLocationService.getLastKnownGeoPoint(this), VIEWS.MAP);
			search(mapView.getCurrentMiddlePoint(), VIEWS.MAP);
		} else if (v == listMode) {
			hideSearchPopup();
			activeView = VIEWS.LIST;
			viewFlipper.setDisplayedChild(1);
			updateList();
		} else if (v == arMode) {
			hideSearchPopup();
			viewFlipper.setDisplayedChild(2);
			activeView = VIEWS.AR;
			search(MyLocationService.getLastKnownGeoPoint(this), VIEWS.AR);
		} else if (v == cancel) {
			hideSearchPopup();
		} else if (v == gasStationChooser) {
			quickAction.show(v);
		}
		benzinskeOverlay.hidePopup();
	}

	private void showSearchPopup() {
		if (!isSearchActivated) {
			searchContainer.setVisibility(View.VISIBLE);
			searchContainer.startAnimation(animShow);
			isSearchActivated = true;
		}
	}

	private void hideSearchPopup() {
		if (isSearchActivated) {

			searchContainer.startAnimation(animHide);
		}
	}

	@Override
	public void onAnimationStart(Animation animation) {
		// NIX

	}

	@Override
	public void onAnimationEnd(Animation animation) {
		if (animation == animHide) {
			searchContainer.setVisibility(View.GONE);
			isSearchActivated = false;
			if (query != null) {
				query.setText("");
			}
		}

	}

	@Override
	public void onAnimationRepeat(Animation animation) {
		// NIX

	}

	@Override
	public boolean onKey(View v, int keyCode, KeyEvent event) {
		if (event.getAction() == KeyEvent.ACTION_UP)
			return false;

		if (keyCode == KeyEvent.KEYCODE_ENTER) {

			if (!TextUtils.isEmpty(query.getText())) {
				if (!lock) {
					lock = true;
					InputMethodManager mgr = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
					mgr.hideSoftInputFromWindow(query.getWindowToken(), 0);
					try {
						String address = query.getText().toString();
						if (address != null && address.length() > 0) {
							Async.doAsync(null, new TravelAssistantGeocoder(this, address), new Outcome<Void, GeoPoint>() {

								@SuppressWarnings("synthetic-access")
								@Override
								protected void succeeded(Void key, GeoPoint result) {
									Log.i(TAG, result.getLatitudeE6() + " " + result.getLongitudeE6());
									search(result, VIEWS.MAP);
									hideSearchPopup();
									lock = false;
								}

								@SuppressWarnings("synthetic-access")
								@Override
								protected void failed(Void key, Throwable t) {
									Toast.makeText(BenzinskeMapActivity.this, "Nix", Toast.LENGTH_SHORT).show();
									lock = false;
									hideSearchPopup();
								}
							}, NotifierFactory.newThreadSpecificNotifier(handler));
						}
					} catch (Exception e) {
						Log.e(TAG, e.getMessage());
					}
				}

			} else {
				Toast.makeText(this, "Nix", Toast.LENGTH_SHORT).show();
				lock = false;

			}
			return true;
		}

		return false;
	}

	@Override
	protected void onStart() {
		super.onStart();
		ActionBar bar = getSupportActionBar();
		if (bar != null) {
			bar.setDisplayHomeAsUpEnabled(true);
		}
	}

	@Override
	public void onBenzinskaSelected() {
		hideSearchPopup();

	}

	@Override
	public void onItemClick(QuickAction source, int pos, int actionId) {
		if (source == quickAction){
			if (actionId == INA_ID){
				activeType = Constant.INA_REGEX;
			} else if (actionId == PETROL_ID){
				activeType = Constant.PETROL_REGEX;
			} else if (actionId == OMV_ID){
				activeType = Constant.OMV_REGEX;
			} else if (actionId == CROBENZ_ID){
				activeType = Constant.CROBENZ_REGEX;
			} else if (actionId == ALL_ID){
				activeType = "";
			}
			//search(MyLocationService.getLastKnownGeoPoint(this), activeView);
			search(mapView.getCurrentMiddlePoint(), activeView);
		}

	}

}
